home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / gprim / discgrp / dgdraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-25  |  7.9 KB  |  235 lines

  1. /* Copyright (c) 1992 The Geometry Center; University of Minnesota
  2.    1300 South Second Street;  Minneapolis, MN  55454, USA;
  3.    
  4. This file is part of geomview/OOGL. geomview/OOGL is free software;
  5. you can redistribute it and/or modify it only under the terms given in
  6. the file COPYING, which you should have received along with this file.
  7. This and other related software may be obtained via anonymous ftp from
  8. geom.umn.edu; email: software@geom.umn.edu. */
  9.  
  10. /* july 25, 1993: I tried to make an improvement in order to make a 
  11.  * better video for my siggraph talk here but decided against it.
  12.  */
  13. /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
  14.  
  15. #include "discgrpP.h"
  16. #include "mgP.h"
  17. #include "math.h"
  18.  
  19.  
  20. DiscGrp *
  21. DiscGrpDraw(register DiscGrp *discgrp)
  22. {
  23.     static HPoint3 origin = {0,0,0,1}, cpos;
  24.     static Transform c2m;   /* it's used in the DiscGrp data struc */
  25.     Transform w2c, c2w, cinv, m2w, w2m,
  26.         m2c, h, hprime, c2wprime;
  27.     Transform invtlate, tmp, tlate;
  28.     DiscGrpEl *nhbr;
  29.     int i, metric;
  30.     float fov, cfov;
  31.     float halfy, aspect, halfx;
  32.     static float magic_scale = 1.4;
  33.  
  34.     metric = discgrp->attributes & DG_METRIC_BITS;
  35.     /*  make sure we have some geometry to display; the control code
  36.      *    is a bit suspiciously topheavy  */
  37.     if (discgrp->geom == NULL || discgrp->flag & DG_NEWDIRDOM ||
  38.     (discgrp->flag & DG_DRAWDIRDOM && discgrp->ddgeom == NULL)) {
  39.           Appearance *ap;
  40.           float scale;
  41.           discgrp->ddgeom = DiscGrpDirDom(discgrp);
  42.     if (discgrp->geom == NULL ) discgrp->geom = discgrp->ddgeom;
  43.         /* turn off the alarm */
  44.     discgrp->flag &= ~DG_NEWDIRDOM;
  45.     if (!discgrp->ddgeom)    {
  46.         OOGLError(1,"DiscGrpDraw: Unable to create dirichlet domain\n");
  47.         }
  48.         }
  49.  
  50.     /* be sure we have some group elements */
  51.     if (discgrp->big_list == NULL )
  52.       if (discgrp->nhbr_list != NULL) 
  53.     discgrp->big_list = discgrp->nhbr_list;
  54.       else     return(discgrp);
  55.  
  56.     /* we're about to mess around with the camera matrix; before doing so,
  57.     get the current one (it's already been set for this frame) to use in
  58.     culling later on */
  59.     if (discgrp->flag  & DG_ZCULL)    {
  60.         /* get the pieces of the model to viewing transform */
  61.     CamGet(_mgc->cam, CAM_W2C, w2c);
  62.         /* concatenate the model to world coordinate transform */
  63.         mg_gettransform(m2w);
  64.         TmConcat(m2w, w2c, m2c);
  65.     CamGet(_mgc->cam, CAM_FOV, &fov);
  66.     CamGet(_mgc->cam, CAM_HALFYFIELD, &halfy);
  67.     CamGet(_mgc->cam, CAM_ASPECT, &aspect);
  68.     halfy = halfy * magic_scale;
  69.     halfx = aspect * halfy;
  70.  
  71.     /* Hack to get culling to work -Celeste */
  72.     halfx = (halfx > halfy) ? halfx : halfy;
  73.     halfy = halfx;
  74.  
  75.     /* use half + a fudge factor to compute cos of angle */
  76.     /* currently this is badly broken so we have to use much bigger
  77.     factor than we should have to */
  78.      fov = magic_scale * (3.14159/180.0) * fov;
  79.     cfov = cos( (double) fov);
  80.     }
  81.  
  82.     /* 
  83.      * the main idea here is to find out the position of the current camera
  84.      * and use it to make sure the group elements used are centered at the 
  85.      * camera.  We do this by looking at the orbit of the origin and seeing
  86.      * if the camera is closer to 
  87.      */
  88.     if (discgrp->flag & DG_CENTERCAM )    {
  89.     /* get the camera transformation */
  90.     CamGet(_mgc->cam, CAM_C2W, c2w);
  91.  
  92.     /* concatenate the model to world coordinate transform */
  93.     mg_gettransform(m2w);
  94.     TmInvert(m2w, w2m);
  95.       TmConcat(c2w, w2m, c2m);
  96.     discgrp->c2m = (float (*)[4]) c2m;
  97.  
  98.     /* use it to derive the model coordinates of the camera */
  99.     HPt3Transform(c2m, &origin, &cpos);    
  100.  
  101.     /* compute the group element which is 'closest' to the camera */
  102.     nhbr = DiscGrpClosestGroupEl(discgrp, &cpos);    
  103.  
  104.     /* apply the inverse of this transform to the camera */
  105.       TmInvert(nhbr->tform, h);
  106.     /* this requires conjugating cinv by the w2m transform: 
  107.      *
  108.          *  C  --- c2w --->   W   ---- w2m ---->   M
  109.      *   \                |                    |
  110.      *    \            h'                 h = nhbr->tform inverse
  111.      *     c2w'          |                    |
  112.      *    \--------->   W   <--- m2w -----   M
  113.      *
  114.      * In the above diagram we want c2w' = c2w h'
  115.        */
  116.     TmConcat(h, m2w, cinv);
  117.     TmConcat(w2m, cinv, hprime);
  118.     TmConcat(c2w, hprime, c2wprime);
  119.     if (discgrp->attributes & DG_HYPERBOLIC && needstuneup(c2wprime)) {
  120.         tuneup(c2wprime, metric);
  121.         if (needstuneup(c2wprime))
  122.             OOGLError(1,"DiscGrpDraw: tuneup failed\n");
  123.         }
  124.     CamSet(_mgc->cam, CAM_C2W, c2wprime, CAM_END);
  125.     }
  126.  
  127.     {
  128.     int viscnt = 0; 
  129.     float ratio = 1.0;
  130.     HPoint3 image, image2;
  131.     int vis;
  132.     float dx, dy, d;
  133.     Transform tile2c;
  134.     extern Geom *large_dd, *small_dd;    /*very ugly but appearances
  135.         don't work correctly when pushed down into a list */
  136.     Transform Tnew, T2;
  137.     GeomIter *it;
  138.  
  139.     it = GeomIterate( (Geom *)discgrp, DEEP );
  140.     /* loop through them */
  141.     while(NextTransform(it, Tnew) > 0) {
  142.     vis = 1;
  143.     if (discgrp->flag  & DG_ZCULL)    {
  144.             TmConcat(Tnew, m2c, tile2c);
  145.             HPt3Transform(tile2c, &discgrp->cpoint, &image);
  146.         d = HPt3SpaceDistance(&image, &discgrp->cpoint, metric);
  147.         if (d > 2.0 )    {    /* only discard far-away tiles */
  148.           /* first discard the ones behind the eye, if that makes sense */
  149.           if (metric != DG_SPHERICAL && image.z*image.w > 0.0) vis = 0;
  150.           else {    /* then test outside the camera frustrum */
  151. /*
  152.             HPt3Dehomogenize(&image, &image2);
  153.         d = sqrt((double)(image2.z*image2.z + image2.x*image2.x));
  154. */
  155.                 if (fabs(image.x) > fabs(image.z * halfx) ) vis = 0;
  156.             else     {
  157. /*
  158.                 HPt3R30Normalize(&image2);
  159.             d = sqrt((double)(image2.z*image2.z + image2.y*image2.y));
  160. */
  161.                     if (fabs(image.y) > fabs(image.z * halfy) ) vis = 0;
  162.                 }
  163.         }
  164.           }
  165.           /* prevent jerky transitions of # of grp els */
  166.           if (d > discgrp->enumdist) vis = 0;
  167.         }
  168.  
  169.     if (vis)    {
  170.       viscnt++;
  171.           mgpushtransform();
  172.           mgtransform( Tnew );
  173.  
  174.       /* while the appearance stuff doesn't work correctly, we have to
  175.        * commit some pretty terrible crimes...we'd like to be able to
  176.        * just say GeomDraw(discgrp->geom)...but we can't as long as
  177.        * appearances don't work as advertised */
  178.  
  179.           if (discgrp->ddgeom && discgrp->flag & DG_DRAWDIRDOM)    {
  180.        if (discgrp->flag & DG_DDBEAM)    GeomDraw(discgrp->ddgeom);
  181.        else {
  182.             mgpushappearance();
  183.             mgctxset(MG_ApSet, AP_DONT, APF_FACEDRAW, AP_DO, APF_EDGEDRAW, AP_END, MG_END);
  184.             GeomDraw(large_dd);
  185.             mgpopappearance();
  186.  
  187.             mgpushappearance();
  188.             mgctxset(MG_ApSet, AP_DO, APF_FACEDRAW, AP_END, MG_END);
  189.             GeomDraw(small_dd);
  190.             mgpopappearance();
  191.             }
  192.        }
  193.           if (discgrp->flag & DG_DRAWGEOM && discgrp->geom && discgrp->geom != discgrp->ddgeom) 
  194.         GeomDraw( discgrp->geom );
  195.  
  196.       if ((discgrp->flag & DG_DRAWCAM) && (discgrp->camgeom)) {
  197.         mgpushtransform();
  198.         mgtransform( c2m );
  199.         GeomDraw(discgrp->camgeom);
  200.         mgpoptransform();
  201.         }
  202.  
  203.           mgpoptransform();
  204.       }
  205.         }
  206.     /* for debugging to see how culling works */
  207.     ratio = viscnt / ((double) discgrp->big_list->num_el);
  208.     }
  209.  
  210.     return(discgrp);
  211. }
  212.  
  213.             
  214. #ifdef REASONABLE
  215.      TmScale( scaler, discgrp->scale, discgrp->scale, discgrp->scale);
  216.     large = DiscGrpDirDom(discgrp, &discgrp->cpoint);
  217.     large->ap = ApCreate(AP_DO, APF_EDGEDRAW, AP_DONT, APF_FACEDRAW, AP_END);
  218.     ap = ApCreate(AP_DONT, APF_EDGEDRAW, AP_DO, APF_FACEDRAW, AP_END);
  219.     small = GeomCreate("inst", CR_GEOM, large, CR_AXIS, scaler, CR_APPEAR, ap, CR_END);
  220.     smlist = GeomCreate("list", CR_GEOM, small, CR_END);
  221.     mylist = GeomCreate("list", CR_GEOM, large, CR_CDR, smlist, CR_END);
  222.     discgrp->ddgeom = mylist;
  223.      TmScale( scaler, discgrp->scale, discgrp->scale, discgrp->scale);
  224.     Tm3SpaceTranslateOrigin(tlate, &discgrp->cpoint, metric);
  225.     /* perform translation so cpoint is at origin */
  226.     TmInvert(tlate, invtlate);
  227.     /* apply scaling transform centered at cpoint */
  228.     TmConcat(invtlate, scaler, tmp);
  229.     /* and move cpoint back to where it started */
  230.     TmConcat(tmp, tlate, tmp);
  231.  
  232.         d = HPt3SpaceDistance( &discgrp->cpoint, &image, metric);
  233. #else
  234. #endif
  235.